#include <future>
#include <iostream>
#include <chrono>
#include <unistd.h>

// 异步任务：计算n的平方
int square(int n) {
    sleep(1);
    return n * n;
}

// 使用默认策略，行为是未定义的，取决于编译器
// std::async(square, 5);
// 在未获取结果之前，即get(), future是有效的
// 获取结果之后，future无效，此时调用get()结果是未定义的

// 简而言之，async就是对一个线程的封装，底层就是创建一个线程去执行可调用对象
// 而future是用来获取async的结果的
// 如果async的返回值没有被接收，或者再调用get()/wait()前被析构了
// 此时主线程就会陷入阻塞，直到可调用对象执行完毕
// 这违背了我们想要异步执行的初衷，所以async的返回值一定要被接收

int main1() {
    // 1. 立即异步执行（std::launch::async）
    std::future<int> fut1 = std::async(std::launch::async, square, 5);
    // 2. 延迟执行（直到调用get()/wait()）
    std::future<int> fut2 = std::async(std::launch::deferred, square, 10);

    std::cout << fut1.valid() << std::endl;
    std::cout << fut2.valid() << std::endl;
    sleep(3);
    std::cout << "等待fut1结果..." << std::endl;
    std::cout << "5的平方: " << fut1.get() << std::endl; // 阻塞约1秒，输出25

    std::cout << "等待fut2结果..." << std::endl;
    std::cout << "10的平方: " << fut2.get() << std::endl; // 此时才执行任务，阻塞约1秒，输出100

    std::cout << fut1.valid() << std::endl;
    std::cout << fut2.valid() << std::endl;

    return 0;
}



#include <future>
#include <thread>
#include <iostream>
#include <chrono>

void thread_task(std::promise<int> prom) {
    std::cout << "子线程：开始执行\n";
    
    // 模拟计算过程
    std::this_thread::sleep_for(std::chrono::seconds(1));
    int result = 42;
    
    // 设置结果，此时主线程的get()会解除阻塞
    prom.set_value(result);
    std::cout << "子线程：已设置结果\n";
    
    // set_value之后，子线程继续执行后续代码
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 再做一些事情
    std::cout << "子线程：后续代码执行完毕，即将退出\n";
}

//当 std::promise 调用 set_value 后，主线程的 std::future::get() 会立即解除阻塞并获取结果，但子线程会继续执行其后续代码，直到线程函数正常结束。
//当 std::promise 调用set_value_at_thread_exit时，主线程的get会继续阻塞，直到从线程执行完后才会获取结果
int main2() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
    
    std::thread t(thread_task, std::move(prom));
    
    std::cout << "主线程：等待结果...\n";
    int result = fut.get(); // 此处会阻塞，直到set_value被调用
    std::cout << "主线程：获取结果：" << result << "\n";
    
    // 主线程可以继续做其他事情（此时子线程仍在执行后续代码）
    std::this_thread::sleep_for(std::chrono::seconds(3));
    std::cout << "主线程：准备等待子线程结束\n";
    
    t.join(); // 等待子线程完全结束
    std::cout << "主线程：程序结束\n";
    return 0;
}


#include <future>
#include <thread>
#include <iostream>
#include <vector>

// 多个线程共享结果并打印
void print_result(std::shared_future<int> sf) {
    // 每个线程都可以调用get()获取结果
    std::cout << "线程 " << std::this_thread::get_id() 
              << " 获取结果：" << sf.get() << std::endl;
}

// future是不可复制，只能移动，get只能调用一次
// shared_future可以多个线程共享结果，get可以调用多次，支持复制
// shared_future可以直接构造，也可以有future.share()
// shared_future::get() 是线程安全的，多个线程可以同时调用（无需额外同步）。

int main3() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
    
    // 将future转换为shared_future（转换后原future失效）
    std::shared_future<int> sf = fut.share();
    
    // 启动3个线程共享结果
    std::vector<std::thread> threads;
    for (int i = 0; i < 3; ++i) {
        threads.emplace_back(print_result, sf); // 复制shared_future
    }
    
    // 设置结果
    prom.set_value(42);
    
    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }
    
    return 0;
}


// 多个线程共享同一个结果
#include <iostream>
#include <future>
#include <thread>
#include <vector>
#include <chrono>
#include <random>

// 模拟耗时计算：生成一个随机数并返回其平方
int compute_square() {
    // 模拟计算耗时
    std::this_thread::sleep_for(std::chrono::seconds(2));
    
    // 生成1-10之间的随机数
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dist(1, 10);
    int num = dist(gen);
    
    std::cout << "计算完成: " << num << " 的平方是 " << num * num << std::endl;
    return num * num;
}

// 处理结果的函数：多个线程将共享同一个结果
void process_result(const std::string& thread_name, std::shared_future<int> shared_fut) {
    std::cout << thread_name << " 等待结果..." << std::endl;
    
    // 多个线程都可以调用get()获取结果
    int result = shared_fut.get();
    
    // 每个线程对结果进行不同的处理
    std::cout << thread_name << " 处理结果: " << result 
              << "，处理后的值: " << result * 2 << std::endl;
}

int main4() {
    std::cout << "程序开始，启动计算任务..." << std::endl;
    
    // 启动异步任务并获取future
    std::future<int> fut = std::async(std::launch::async, compute_square);
    
    // 将future转换为shared_future，以便多个线程共享
    std::shared_future<int> shared_fut = fut.share();
    
    // 创建多个线程来处理结果
    std::vector<std::thread> threads;
    threads.emplace_back(process_result, "处理线程1", shared_fut);
    threads.emplace_back(process_result, "处理线程2", shared_fut);
    threads.emplace_back(process_result, "处理线程3", shared_fut);
    
    // 等待所有处理线程完成
    for (auto& t : threads) {
        t.join();
    }
    
    std::cout << "所有线程处理完毕，程序结束" << std::endl;
    return 0;
}


// package_task
// 对可调用对象进行封装，让其与future绑定起来，可以用future获取该可调用对象的结果
// pakcage_task 不可复制，只能移动
// 可以定义一个空的package_task，此时它是无效的
// 一个package_task只能被调用一次，如果需要重新调用，则需要reset
#include <iostream>
#include <future>
#include <thread>
#include <chrono>

// 1. 定义一个普通函数作为任务
int calculate_sum(int a, int b) {
    std::cout << "任务开始执行...\n";
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
    return a + b;
}

int main5() {
    // 2. 创建packaged_task，包装任务（签名为int(int, int)）
    std::packaged_task<int(int, int)> task(calculate_sum);

    // 3. 获取与任务关联的future
    std::future<int> fut = task.get_future();

    // 4. 在新线程中执行任务（需要移动传递task，因为它不可复制）
    std::thread t(std::move(task), 10, 20); // 传递参数10和20

    // 5. 主线程可以做其他事情
    std::cout << "等待任务结果...\n";

    // 6. 通过future获取结果（阻塞直到任务完成）
    int result = fut.get();
    std::cout << "任务结果：10 + 20 = " << result << "\n";

    // 等待线程结束
    t.join();
    return 0;
}
    


#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <chrono>

// 工作线程入口函数
void worker_thread(
    std::queue<std::packaged_task<void()>>& task_queue,
    std::mutex& mtx,
    std::condition_variable& cv,
    bool& stop_flag
) {
    std::cout << "工作线程启动\n";
    
    while (true) {
        std::packaged_task<void()> task;
        
        // 等待并获取任务
        {
            std::unique_lock<std::mutex> lock(mtx);
            cv.wait(lock, [&]() { 
                return stop_flag || !task_queue.empty(); 
            });
            
            // 检查退出条件
            if (stop_flag && task_queue.empty()) {
                break;
            }
            
            // 取出任务
            task = std::move(task_queue.front());
            task_queue.pop();
        }
        
        // 执行任务
        task();
    }
    
    std::cout << "工作线程退出\n";
}

// 示例任务函数
void task1() {
    std::cout << "执行任务1 (耗时1秒)\n";
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

int task2(int a, int b) {
    std::cout << "执行任务2: " << a << " + " << b << "\n";
    return a + b;
}

int main() {
    // 共享数据结构
    std::queue<std::packaged_task<void()>> task_queue;
    std::mutex mtx;
    std::condition_variable cv;
    bool stop_flag = false;
    
    // 启动工作线程
    std::thread worker(worker_thread, 
                      std::ref(task_queue), 
                      std::ref(mtx), 
                      std::ref(cv), 
                      std::ref(stop_flag));
    
    // 主线程创建并添加任务
    // 任务1：无返回值
    {
        std::packaged_task<void()> task(task1);
        std::future<void> fut = task.get_future();
        {
            std::lock_guard<std::mutex> lock(mtx);
            task_queue.push(std::move(task));
        }
        cv.notify_one();
        fut.get(); // 等待任务1完成
    }
    
    // 任务2：有返回值（修复包装方式）
    {
        // 使用shared_ptr确保包装的任务对象生命周期安全
        auto task2_ptr = std::make_shared<std::packaged_task<int(int, int)>>(task2);
        std::future<int> fut = task2_ptr->get_future();
        
        // 正确包装带参数的任务
        std::packaged_task<void()> wrapper([task2_ptr]() {
            (*task2_ptr)(10, 20);
        });
        
        {
            std::lock_guard<std::mutex> lock(mtx);
            task_queue.push(std::move(wrapper));
        }
        cv.notify_one();
        
        // 获取任务2的结果
        std::cout << "任务2结果: " << fut.get() << "\n";
    }
    
    // 任务3：lambda表达式任务
    {
        std::packaged_task<void()> task([]() {
            std::cout << "执行任务3 (lambda)\n";
        });
        {
            std::lock_guard<std::mutex> lock(mtx);
            task_queue.push(std::move(task));
        }
        cv.notify_one();
    }
    
    // 等待所有任务执行完毕
    std::this_thread::sleep_for(std::chrono::seconds(2));
    
    // 发送停止信号
    {
        std::lock_guard<std::mutex> lock(mtx);
        stop_flag = true;
    }
    cv.notify_one();
    
    // 等待工作线程结束
    worker.join();
    std::cout << "主线程结束\n";
    
    return 0;
}
    
    